package com.zjhb.common.dao;

/**
 * 封装hibernate公共方法
 * 
 */
import java.io.Serializable;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class BaseDaoImpl implements BaseDao {
	@Autowired
	protected SessionFactory sessionFactory;
	protected static Logger logger = Logger.getLogger(BaseDaoImpl.class);

	@Override
	public <T> void saveOrUpdate(T entity) {
		getSession().saveOrUpdate(entity);
	}

	@Override
	public int executeData(String hql) {
		try {
			return getSession().createQuery(hql).executeUpdate();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public <T> List<T> findByHql(String hql) {
		List<T> list = null;
		try {
			list = (List<T>) getSession().createQuery(hql).list();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	public int executeBySql(String sql) {
		try {
			return getSession().createSQLQuery(sql).executeUpdate();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public <T> List<T> findBySql(String sql) {
		try {
			return getSession().createSQLQuery(sql).list();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public <T> boolean update(T entity) {
		boolean bool = false;
		try {
			getSession().update(entity);
			bool = true;
		} catch (Exception e) {
			bool = false;
			throw new RuntimeException(e);
		}
		return bool;
	}

	@Override
	public <T> boolean delete(T entity) {
		boolean bool = false;
		try {
			getSession().delete(entity);
			bool = true;
		} catch (Exception e) {
			bool = false;
			throw new RuntimeException(e);
		}
		return bool;
	}

	@Override
	public <T> T getById(Class<T> clazz, Serializable id) {
		T t = null;
		try {
			t = (T) getSession().get(clazz, id);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return t;
	}

	@Override
	public <T> T getByHql(String hql) {
		T t = null;
		try {
			t = (T) getSession().createQuery(hql).setMaxResults(1).uniqueResult();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return t;
	}

	@Override
	public <T> List<T> getList(String hql) {
		List<T> list = null;
		try {
			list = (List<T>) getSession().createQuery(hql).list();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return list;
	}

	@Override
	public boolean remove(String hql) {
		boolean bool = false;
		try {
			bool = this.executeBySql(hql) > 0 ? true : false;
		} catch (Exception e) {
			bool = false;
			throw new RuntimeException(e);
		}
		return bool;
	}

	@Override
	public Criteria getCriteria(Class<?> clazz) {
		// TODO Auto-generated method stub
		return getSession().createCriteria(clazz);
	}

	@Override
	public int editNumHql(String hql,Object[] objs) {
		Query query= getSession().createQuery(hql);
		if(objs.length>0) {
			for(int i=0;i<objs.length;i++) {
				query.setParameter(i, objs[i]);
			}
		}
		return query.executeUpdate();

	}

	@Override
	public <T> List<T> getList(Class<T> clazz) {
		// TODO Auto-generated method stub
		return getCriteria(clazz).list();
	}

	@Override
	public <T> List<T> getList(String hql, Object[] obj, int first, int maxResults) {
		Query query = getSession().createQuery(hql);
		query.setFirstResult(first);
		query.setMaxResults(maxResults);
		Page<T> page = new Page<>();
		for (int i = 0; i < obj.length; i++) {
			query.setParameter(i, obj[i]);
		}
		return query.list();
	}

	@Override
	public <T> List<T> getList(String hql, int first, int maxResults) {
		Query query = getSession().createQuery(hql);
		query.setFirstResult(first);
		query.setMaxResults(maxResults);
		return query.list();
	}

	@Override
	public Session getSession() {
		// TODO Auto-generated method stub
		return sessionFactory.getCurrentSession();
	}

	@Override
	public <T> Page<T> getList(Criteria criteria, int first, int maxResults) {
		Page<T> page = new Page<>();
		Long total = (Long) criteria.setProjection(Projections.rowCount()).uniqueResult();
		page.setTotal(total);
		criteria.setFirstResult(first);
		criteria.setMaxResults(maxResults);
		page.setRows(criteria.list());
		return page;
	}

	@Override
	public <T> void save(T entity) {
		getSession().save(entity);

	}

	@Override
	public <T> void save(List<T> list) {
		Session session = getSession();
		for (int i = 0; i < list.size(); i++) {
			session.save(list.get(i));
			if (i % 100 == 0) {
				session.flush();
				session.clear();
			}
		}

	}

	@Override
	public <T> boolean delete(Class<T> clazz, Serializable id) {
		// TODO Auto-generated method stub
		try {
			T t=(T) getSession().get(clazz, id);
			getSession().delete(t);
			return true;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public Long getCount(Criteria crt) {
		crt.setMaxResults(10);
		crt.setFirstResult(0);
		Long totalNum = (Long) crt.setProjection(Projections.rowCount()).uniqueResult();
	    if(totalNum==null){
	    	totalNum= (long) 0;
	    }
		return totalNum;
	}

}